// GetThisParameterType

class Dong {
  name: string;
  constructor() {
    this.name = 'dong';
  }
  hello() {
    return `hello ${this.name}`;
  }
}

const dong = new Dong();
dong.hello(); // 'hello dong'

// 通过call改变this的方式来调用
// call 调用的时候，this 就变了，但这里却没有被检查出来 this 指向的错误。
dong.hello.call({ name: 'xk' });

// 如何让编译器能够检查出 this 指向的错误呢？
// 可以在方法声明时指定 this 的类型：

class Dong2 {
  name: string;
  constructor() {
    this.name = 'dong';
  }
  hello(this: Dong, str?: string) {
    return `hello ${this.name} ${str}`;
  }
}

const dong2 = new Dong2();
// @ts-ignore
dong2.hello.call({ name: 'a' }); // 报错 不能强制更改this指向

// 获取this类型
type GetThisParameterType<T> = T extends (this: infer ThisType, ...args: any[]) => any
  ? ThisType
  : unknown;

type res = GetThisParameterType<typeof dong.hello>; // type res = unknown
type res2 = GetThisParameterType<typeof dong2.hello>; // type res2 = Dong

// 其ts中内置的ThisParameterType类型与以上一致

export {};
